import importlib
import os
import sys
import tkinter
import tkinter.ttk
from tkinter.messagebox import showerror, showinfo, showwarning

import customtkinter
from customtkinter import filedialog
from PIL import Image

from classes.album import Album
from classes.track import Track

customtkinter.set_appearance_mode("System")
customtkinter.set_default_color_theme("green")


class TrackFrame(customtkinter.CTkFrame):
    def __init__(self, *args, header_name="Track Info", **kwargs):
        super().__init__(*args, **kwargs)

        self.header_name = header_name

        self.header = customtkinter.CTkLabel(
            self, text=self.header_name, width=30, height=40
        )
        self.header.grid(row=0, column=0, columnspan=2, padx=10, pady=10, sticky="ew")

        self.track_number = customtkinter.CTkLabel(master=self, text="Трек №")
        self.track_number.grid(
            row=1, column=0, columnspan=2, padx=10, pady=10, sticky="w"
        )

        self.track_name = customtkinter.CTkLabel(master=self, text="Sample Name")
        self.track_name.grid(
            row=2, column=0, columnspan=1, padx=10, pady=10, sticky="w"
        )
        self.artist = customtkinter.CTkLabel(master=self, text="Artist")
        self.artist.grid(row=3, column=0, columnspan=1, padx=10, pady=10, sticky="w")
        self.genre = customtkinter.CTkLabel(master=self, text="Sample Genre")
        self.genre.grid(row=4, column=0, columnspan=1, padx=10, pady=10, sticky="w")
        self.subgenre = customtkinter.CTkLabel(master=self, text="Sample Subgenre")
        self.subgenre.grid(row=5, column=0, columnspan=1, padx=10, pady=10, sticky="w")
        self.comment = customtkinter.CTkLabel(master=self, text="Sample Comment")
        self.comment.grid(row=6, column=0, columnspan=1, padx=10, pady=10, sticky="w")
        self.year = customtkinter.CTkLabel(master=self, text="Sample Year")
        self.year.grid(row=7, column=0, columnspan=1, padx=10, pady=10, sticky="w")

        self.grid_columnconfigure(0, weight=1)
        self.grid_columnconfigure(1, weight=2)


class AlbumFrame(customtkinter.CTkFrame):
    def __init__(self, *args, header_name="Album Info", **kwargs):
        super().__init__(*args, **kwargs)

        self.header_name = header_name

        self.header = customtkinter.CTkLabel(
            self, text=self.header_name, width=100, height=50
        )
        self.header.grid(row=0, column=0, columnspan=2, padx=10, pady=10)

        self.track_number = customtkinter.CTkLabel(master=self, text="Трек №")
        self.track_number.grid(row=1, column=0, columnspan=2, padx=10, pady=10)

        self.album_name = customtkinter.CTkLabel(master=self, text="Sample Name")
        self.album_name.grid(row=2, column=0, columnspan=2, padx=10, pady=10)

        self.artist = customtkinter.CTkLabel(master=self, text="Sample Artist")
        self.artist.grid(row=3, column=0, columnspan=2, padx=10, pady=10)
        self.artists = customtkinter.CTkLabel(master=self, text="Sample Artists")
        self.artists.grid(row=4, column=0, columnspan=2, padx=10, pady=10)
        self.genre = customtkinter.CTkLabel(master=self, text="Sample Genre")
        self.genre.grid(row=5, column=0, columnspan=2, padx=10, pady=10)
        self.subgenre = customtkinter.CTkLabel(master=self, text="Sample Subgenre")
        self.subgenre.grid(row=6, column=0, columnspan=2, padx=10, pady=10)
        self.comment = customtkinter.CTkLabel(master=self, text="Sample Comment")
        self.comment.grid(row=7, column=0, columnspan=2, padx=10, pady=10)
        self.year = customtkinter.CTkLabel(master=self, text="Sample Year")
        self.year.grid(row=8, column=0, columnspan=2, padx=10, pady=10)


class BrandFrame(customtkinter.CTkFrame):
    def __init__(self, *args, header_name="Brand", **kwargs):
        super().__init__(*args, **kwargs)

        self.header_name = header_name

        self.header = customtkinter.CTkLabel(
            self, text=self.header_name, width=100, height=50
        )
        self.header.grid(row=0, column=0, padx=10, pady=10)

        self.brand = customtkinter.StringVar(value="")

        self.uncaged_button = customtkinter.CTkRadioButton(
            self, text="Uncaged", value="Uncaged", variable=self.brand
        )
        self.uncaged_button.grid(row=0, column=0, pady=10)
        self.instinct_button = customtkinter.CTkRadioButton(
            self, text="Instinct", value="Instinct", variable=self.brand
        )
        self.instinct_button.grid(row=0, column=1, pady=10)
        self.silk_button = customtkinter.CTkRadioButton(
            self, text="Silk", value="Silk", variable=self.brand
        )
        self.silk_button.grid(row=0, column=2, pady=10)
        self.none_button = customtkinter.CTkRadioButton(
            self, text="None", value="None", variable=self.brand
        )
        self.none_button.grid(row=0, column=3, pady=10)

    def get_value(self):
        """returns selected value as a string, returns an empty string if nothing selected"""
        return self.brand.get()

    def set_value(self, selection):
        """selects the corresponding radio button, selects nothing if no corresponding radio button"""
        self.brand.set(selection)


class TypeFrame(customtkinter.CTkFrame):
    def __init__(self, *args, header_name="Release Type", **kwargs):
        super().__init__(*args, **kwargs)

        self.header_name = header_name

        self.header = customtkinter.CTkLabel(
            self, text=self.header_name, width=100, height=50
        )
        self.header.grid(row=0, column=0, padx=10, pady=10)

        self.type = customtkinter.StringVar(value="")

        self.single_button = customtkinter.CTkRadioButton(
            self, text="Single", value="Single", variable=self.type
        )
        self.single_button.grid(row=0, column=0, pady=10)
        self.ep_button = customtkinter.CTkRadioButton(
            self, text="EP", value="EP", variable=self.type
        )
        self.ep_button.grid(row=0, column=1, pady=10)
        self.lp_button = customtkinter.CTkRadioButton(
            self, text="LP", value="LP", variable=self.type
        )
        self.lp_button.grid(row=0, column=2, pady=10)

    def get_value(self):
        """returns selected value as a string, returns an empty string if nothing selected"""
        return self.type.get()

    def set_value(self, selection):
        """selects the corresponding radio button, selects nothing if no corresponding radio button"""
        self.type.set(selection)


class App(customtkinter.CTk):
    def __init__(self):
        super().__init__()

        self.title("Music Post Maker")
        self.minsize(800, 600)
        self.protocol("WM_DELETE_WINDOW", self.exit_app)

        self.cover = customtkinter.CTkImage(
            Image.open("images/cover.png"),
            size=(350, 350),
        )
        self.cover_label = customtkinter.CTkLabel(
            master=self, text="", image=self.cover
        )

        self.track_open = customtkinter.CTkButton(
            master=self, command=self.track_open_callback, text="Open Track"
        )
        self.album_open = customtkinter.CTkButton(
            master=self, command=self.album_open_callback, text="Open Album"
        )

        self.single_post = customtkinter.CTkButton(
            master=self,
            command=self.make_single_post,
            text="Copy post for single",
        )

        self.album_post = customtkinter.CTkButton(
            master=self,
            command=self.make_album_post,
            text="Copy post for album",
        )

        self.track_block = TrackFrame(self)

        self.album_block = AlbumFrame(self)

        self.brand_block = BrandFrame(self)

        self.type_block = TypeFrame(self)
        self.type_block.single_button.configure(state=tkinter.DISABLED)
        self.type_block.ep_button.configure(state=tkinter.DISABLED)
        self.type_block.lp_button.configure(state=tkinter.DISABLED)

        self.grid_rowconfigure((0, 1, 2, 3, 4, 5), weight=1)
        self.grid_columnconfigure((0, 1), weight=1)

        self.cover_label.grid(row=0, column=0, rowspan=3, padx=20, pady=10)
        self.track_open.grid(row=3, column=0, padx=10, pady=10)
        self.album_open.grid(row=4, column=0, padx=10, pady=20)

        self.track_block.grid(
            row=0, column=1, rowspan=3, columnspan=2, padx=10, pady=10, sticky="nsew"
        )

        self.brand_block.grid(
            row=3, column=1, rowspan=1, columnspan=2, padx=10, pady=10, sticky="nsew"
        )

        self.type_block.grid(
            row=4, column=1, rowspan=1, columnspan=2, padx=10, pady=10, sticky="nsew"
        )

        self.single_post.grid(
            row=5, column=1, rowspan=1, columnspan=1, padx=10, pady=20
        )

    def disable_types(self):
        self.type_block.single_button.deselect()
        self.type_block.ep_button.deselect()
        self.type_block.lp_button.deselect()
        self.type_block.single_button.configure(state=tkinter.DISABLED)
        self.type_block.ep_button.configure(state=tkinter.DISABLED)
        self.type_block.lp_button.configure(state=tkinter.DISABLED)

    def track_open_callback(self):
        trackpath = filedialog.askopenfilename(initialdir="E:\YandexDisk\Monstercat")
        if trackpath[-4:] == "flac":
            self.disable_types()
            self.type_block.single_button.configure(state=tkinter.NORMAL)
            self.type_block.single_button.select()

            self.album_block.grid_forget()
            self.album_post.grid_forget()

            self.track = Track(trackpath)
            print(self.track)

            self.track_block.track_name.configure(text=f"Name: {self.track.name}")
            self.track_block.artist.configure(text=f"Artist: {self.track.artists}")
            self.track_block.genre.configure(text=f"Genre: {self.track.genre}")
            self.track_block.subgenre.configure(text=f"Subgenre: {self.track.subgenre}")
            self.track_block.year.configure(text=f"Year: {self.track.year}")
            self.track_block.comment.configure(
                text=f"Release Day: {self.track.day} {self.track.month}"
            )

            with open("cover.jpg", "wb") as file:
                file.write(self.track.cover)

            self.cover = customtkinter.CTkImage(
                Image.open("cover.jpg"),
                size=(350, 350),
            )

            self.cover_label.configure(image=self.cover)

            self.track_block.grid(
                row=0, column=1, rowspan=3, columnspan=2, padx=10, pady=10
            )
            self.single_post.grid(
                row=5, column=1, rowspan=1, columnspan=1, padx=10, pady=20
            )
        elif trackpath == "":
            pass
        else:
            showerror(title="Error", message="FLAC file is required.")

    def album_open_callback(self):
        trackspaths = filedialog.askopenfilenames(initialdir="E:\YandexDisk\Monstercat")
        if len(trackspaths) > 2:
            self.disable_types()
            self.type_block.ep_button.configure(state=tkinter.NORMAL)
            self.type_block.lp_button.configure(state=tkinter.NORMAL)

            self.album = Album(trackspaths)

            self.track_block.grid_forget()
            self.single_post.grid_forget()

            self.album_block.album_name.configure(text=f"Album Name: {self.album.name}")
            self.album_block.artist.configure(
                text=f"Album Artist: {self.album.album_artists}"
            )
            self.album_block.artists.configure(text=f"Artists: {self.album.artists}")
            self.album_block.genre.configure(text=f"Genre: {self.album.genre}")
            self.album_block.subgenre.configure(text=f"Subgenre: {self.album.subgenre}")
            self.album_block.year.configure(text=f"Year: {self.album.year}")
            self.album_block.comment.configure(
                text=f"Release Day: {self.album.day} {self.album.month}"
            )

            with open("cover.jpg", "wb") as file:
                file.write(self.album.cover)
            self.cover = customtkinter.CTkImage(
                Image.open("cover.jpg"),
                size=(350, 350),
            )
            self.cover_label.configure(image=self.cover)

            self.album_block.grid(
                row=0, column=1, rowspan=3, columnspan=2, padx=10, pady=10
            )
            self.album_post.grid(
                row=5, column=1, rowspan=1, columnspan=1, padx=10, pady=20
            )
        elif len(trackspaths) == 1:
            showwarning(
                title="Amount Error",
                message="Album cannot be single track.",
            )

    def make_single_post(self):
        brand = self.brand_block.get_value()
        type = self.type_block.get_value()
        if brand and type:
            try:
                self.track.brand = brand
                self.track.type = type
                templatepath = filedialog.askopenfilename(initialdir="templates")
                if templatepath[-3:] == ".py":
                    spec = importlib.util.spec_from_file_location(
                        "single_template", templatepath
                    )
                    single_template = importlib.util.module_from_spec(spec)
                    sys.modules["single_template"] = single_template
                    spec.loader.exec_module(single_template)
                    try:
                        post = single_template.get_post(track=self.track)
                        self.clipboard_clear()
                        self.clipboard_append(post)
                        showinfo(title="Success", message="Post successfully copied.")
                    except Exception as e:
                        print(e)
                        showerror(
                            title="Template Error",
                            message="Select another template file or check the selected one for errors.",
                        )
            except:
                showerror(
                    title="File Error",
                    message="Track not selected.",
                )

    def make_album_post(self):
        brand = self.brand_block.get_value()
        type = self.type_block.get_value()
        if brand:
            try:
                templatepath = filedialog.askopenfilename(initialdir="templates")
                self.album.brand = brand
                self.album.type = type
                if templatepath[-3:] == ".py":
                    spec = importlib.util.spec_from_file_location(
                        "album_template", templatepath
                    )
                    album_template = importlib.util.module_from_spec(spec)
                    sys.modules["album_template"] = album_template
                    spec.loader.exec_module(album_template)
                    try:
                        post = album_template.get_post(album=self.album)
                        self.clipboard_clear()
                        self.clipboard_append(post)
                        showinfo(title="Success", message="Post successfully copied.")
                    except Exception as e:
                        print(e)
                        showerror(
                            title="Template Error",
                            message="Select another template file or check the selected one for errors.",
                        )
            except:
                showerror(
                    title="Files Error",
                    message="Album tracks not selected.",
                )

    def exit_app(self):
        if os.path.isfile("cover.jpg"):
            os.remove("cover.jpg")
        self.destroy()


if __name__ == "__main__":
    app = App()
    app.mainloop()
